package com.markhsiu.minimq.core.thread;

import static com.markhsiu.minimq.core.constant.ConstantUtil.checkArgument;
import static com.markhsiu.minimq.core.constant.ConstantUtil.checkNotNull;

import java.util.Locale;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;

/**
 *  
 * 线程工厂构建类
 */
public final class ThreadFactoryBuilder {
	
	private String nameFormat = null;
	private Boolean daemon = null;
	private Integer priority = null;
	private ThreadFactory backingThreadFactory = null;


	/**
	 * 默认线程名称 ：MiniMQConnectFactory-1-thread-
	 *  默认为不为守护线程，不跟着主线程一起死亡
	 *  默认线程优先级为5
	 */
	public ThreadFactoryBuilder() {
		this.nameFormat = "MiniMQConnectFactory";
		this.daemon = false;
	     this.priority =Thread.NORM_PRIORITY;
	}


	public ThreadFactoryBuilder setNameFormat(String nameFormat) {
		this.nameFormat = nameFormat;
		return this;
	}


	public ThreadFactoryBuilder setDaemon(boolean daemon) {
		this.daemon = daemon;
		return this;
	}


	public ThreadFactoryBuilder setPriority(int priority) {

		checkArgument(priority >= Thread.MIN_PRIORITY,
				"Thread priority (%s) must be >= %s", priority,
				Thread.MIN_PRIORITY);
		checkArgument(priority <= Thread.MAX_PRIORITY,
				"Thread priority (%s) must be <= %s", priority,
				Thread.MAX_PRIORITY);
		this.priority = priority;
		return this;
	}


 
	public ThreadFactoryBuilder setThreadFactory( ThreadFactory backingThreadFactory) {
		this.backingThreadFactory = checkNotNull(backingThreadFactory);
		return this;
	}


	public ThreadFactory build() {
		return build(this);
	}

	private static ThreadFactory build(ThreadFactoryBuilder builder) {
		final String nameFormat = builder.nameFormat +"-%d-thread-";
		final Boolean daemon = builder.daemon;
		final Integer priority = builder.priority;
		final ThreadFactory backingThreadFactory = (builder.backingThreadFactory != null) ? builder.backingThreadFactory
				: Executors.defaultThreadFactory();
		final AtomicLong count = (nameFormat != null) ? new AtomicLong(0)  : null;
		
		return new ThreadFactory() {
			
			@Override
			public Thread newThread(Runnable runnable) {
				   Thread thread = backingThreadFactory.newThread(runnable);
					thread.setName(format(nameFormat, count.getAndIncrement()));
					thread.setDaemon(daemon);
					thread.setPriority(priority);
				return thread;
			}
		};
	}

	private static String format(String format, Object... args) {
		return String.format(Locale.ROOT, format, args);
	}
}
